package com.nulldev.util.io;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.MessageDigest;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.bind.DatatypeConverter;

import com.nulldev.util.java.ProcessUtil;
import com.nulldev.util.logging.Logger;
import com.nulldev.util.logging.LoggerFactory;
import com.nulldev.util.os.OSUtil;
import com.nulldev.util.string.StringsUtil;

public class MD5Utils {
//	   public static byte[] createChecksum(String filename) throws Exception {
//	       InputStream fis =  new FileInputStream(filename);
//
//	       byte[] buffer = new byte[1024];
//	       MessageDigest complete = MessageDigest.getInstance("MD5");
//	       int numRead;
//
//	       do {
//	           numRead = fis.read(buffer);
//	           if (numRead > 0) {
//	               complete.update(buffer, 0, numRead);
//	           }
//	       } while (numRead != -1);
//
//	       fis.close();
//	       return complete.digest();
//	   }
//
//	   public static String getMD5Checksum(String filename) throws Exception {
//	       byte[] b = createChecksum(filename);
//	       String result = "";
//
//	       for (int i = 0; i < b.length; i++) {
//	           result += Integer.toString((b[i] & 0xff) + 0x100, 16).substring(1);
//	       }
//	       return result;
//	   }
	
    /**
     * Generates an MD5 checksum as a String.
     * @param file The file that is being checksummed.
     * @return Hex string of the checksum value.
     * @throws NoSuchAlgorithmException
     * @throws IOException
     */
    public static String generate(File file) throws Exception {
        MessageDigest messageDigest = MessageDigest.getInstance("MD5");
        messageDigest.update(FileUtil.read(file));
        byte[] hash = messageDigest.digest();

        return DatatypeConverter.printHexBinary(hash).toUpperCase();
    }

	private static final Logger log = LoggerFactory.getLogger();
	private static int fails = 0;
	public static boolean compare(final String md5, final File toComapre) {
		try {
			final String fH = generate(toComapre);
			//System.out.println(fH + " | " + md5);
			if (!fH.equals(md5)) {
				fails += 1;
			}
			return fH.equals(md5);
		}catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}
	
	public static boolean isValidMD5(String s) {
	    return s.matches("[a-fA-F0-9]{32}");
	}
	
	public static boolean isValidSHA1(String s) {
	    return s.matches("[a-fA-F0-9]{40}");
	}
	
	public static String getMD5Hex(final String inputString) {
		try {
		    MessageDigest md = MessageDigest.getInstance("MD5");
		    md.update(inputString.getBytes());

		    byte[] digest = md.digest();

		    return convertByteToHex(digest);
		}catch (Exception e) {
			return inputString;
		}
	}
	
	public static String getMD5Hex(final byte[] input) {
		try {
		    MessageDigest md = MessageDigest.getInstance("MD5");
		    md.update(input);

		    byte[] digest = md.digest();

		    return convertByteToHex(digest);
		}catch (Exception e) {
			return null;
		}
	}
	
	public static String getMD5Hex(final String[] inputStrings) {
		try {
		    MessageDigest md = MessageDigest.getInstance("MD5");
		    //md.update(inputStrings.getBytes());
		    for (final String i : inputStrings) {
		    	md.update(i.getBytes());
		    }

		    byte[] digest = md.digest();

		    return convertByteToHex(digest);
		}catch (Exception e) {
			return StringsUtil.generateSecure(32);
		}
	}

	private static String convertByteToHex(byte[] byteData) {

	    StringBuilder sb = new StringBuilder();
	    for (int i = 0; i < byteData.length; i++) {
	        sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
	    }

	    return sb.toString();
	}

	public static String getMD5HexT(final String data) {
		try {
			return getMD5Hex(data);
		}catch (Exception e) {
			return "";
		}
	}

	public static int findHash(final String[] split) {
		for (int i = 0; i < split.length; i++) {
			final String s = split[i];
			if (isValidMD5(s) || isValidSHA1(s)) {
				return i;
			}
		}
		return -1;
	}
	
	public static byte[] createChecksum(final File filename) throws Exception {
	       InputStream fis = new FileInputStream(filename);

	       byte[] buffer = new byte[1024];
	       MessageDigest complete = MessageDigest.getInstance("MD5");
	       int numRead;

	       do {
	           numRead = fis.read(buffer);
	           if (numRead > 0) {
	               complete.update(buffer, 0, numRead);
	           }
	       } while (numRead != -1);

	       fis.close();
	       return complete.digest();
	   }

	   // faster way to convert
	   // a byte array to a HEX string
	   public static String getMD5Checksum(final File filename) throws Exception {
	       byte[] b = createChecksum(filename);
	       String result = "";

	       for (int i=0; i < b.length; i++) {
	           result += Integer.toString( ( b[i] & 0xff ) + 0x100, 16).substring( 1 );
	       }
	       return result;
	   }
}
